package com.feri.fc.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.feri.fc.config.RocketMQConfig;
import com.feri.fc.dao.OrderDao;
import com.feri.fc.dao.OrderLogDao;
import com.feri.fc.entity.Order;
import com.feri.fc.entity.OrderLog;
import com.feri.fc.order.service.OrderService;
import com.feri.fc.order.sign.SignUtil;
import com.feri.fc.param.OrderAdd;
import com.feri.fc.pay.alipay.AliPayUtil;
import com.feri.fc.pay.util.PayUtil;
import com.feri.fc.strategy.AliPayStrategy;
import com.feri.fc.strategy.PayStrategyContext;
import com.feri.fc.type.OrderStatus;
import com.feri.fc.vo.R;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

/**
 * 指尖造梦，精益求精！
 *
 * @Author：Feri
 * @Date：2024/12/2 11:04
 * @Modified：
 */
@Service
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final OrderDao dao;
    private final OrderLogDao logDao;

    private final RocketMQTemplate rocketMQTemplate;

    @Override
    public R createOrder(OrderAdd add, Integer uid) {
        //1.参数校验 jsr303
        //接口的签名校验 接口在调用过程中，一旦被人抓取到了接口，获取数据并对数据进行篡改
        //调用方和接收方 都按照相同的格式进行参数加密 生成签名(sign)
        //1.调用方 按照规则 对请求参数(sign参数不参与)生成签名的值，赋值sign参数
        //2.接收方 接到请求按照规则 对请求参数(sign参数不参与)生成签名的值
        //3.接收方 比对2个签名的值，如果一致说明安全 ，不一致说明不安全
        //设计签名规则
        //验证签名
        if(!Objects.equals(add.getSign(), SignUtil.createSign(SignUtil.parseMap(OrderAdd.class,add),uid))){
            return R.fail("亲，非法请求，请立即终止！");
        }
        //2.查询就诊人 交叉日期是否存在陪诊服务
        //同一天 只能有1个陪诊订单 改进 可以精确到小时
        LambdaQueryWrapper<Order> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(Order::getPatientId,add.getPatientId());
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        wrapper.like(Order::getStartTime,sdf.format(add.getStartTime()));
        wrapper.eq(Order::getStatus,"未开始");
        wrapper.last(" limit 1");
        Order order=dao.selectOne(wrapper);
        if(order!=null){
            return R.fail("亲，该就诊人在当日已有陪诊预约了，请勿重复！");
        }
        //3.可以下单
        order=new Order(uid);
        BeanUtils.copyProperties(add,order);
        //最长32 不重复
        order.setNo("o"+System.currentTimeMillis()+""+add.getPatientId()+""+add.getRid());
        order.setTitle("预约"+sdf.format(add.getStartTime())+"日陪诊服务");
        dao.insert(order);
        //日志
        logDao.insert(new OrderLog(order.getId(),order.getStatus(),"预约陪诊订单，等待付款"));
        //调用支付 pc端和智能终端（二维码）
        // 移动端（安卓、ios、鸿蒙、小程序）都不需要服务端写，都是直接打开本地的app(支付宝或微信)发起支付
        // 无论是哪种，服务端都需要写回调接口
        //多种支付方式 可以考虑更改为策略模式
        String pay="";
        if(add.getPayType().equals("支付宝")){
            pay=new PayStrategyContext(new AliPayStrategy()).createPay(order.getTitle(), order.getNo(),order.getPayMoney());
        }else if(add.getPayType().equals("微信支付")){

        }
        //生成 支付日志
        //异步 发送 10分钟 未付款成功 自动取消订单  延迟消息 10分钟
        rocketMQTemplate.syncSend(RocketMQConfig.TOPIC_ORDERTO,
                MessageBuilder.withPayload(order.getId()).build(),
                10000,14);

        return R.ok(pay);
    }

    @Override
    public Integer updateOrder(String no, String status) {
        //1.查询订单
        Order order=dao.selectOne(new LambdaQueryWrapper<Order>().eq(Order::getNo,no));
        //2.更新订单状态
        String sta=PayUtil.getPayStatus(status);
        if(sta.equals("支付完成")){
            order.setStatus(OrderStatus.NOASS.getValue());
        }else {
            order.setStatus(OrderStatus.PAYFAIL.getValue());
        }
        order.setUpdateTime(new Date());
        Integer r=dao.updateById(order);
        logDao.insert(new OrderLog(order.getId(),order.getStatus(),"订单状态已更新"));

        return r;
    }

    @Override
    public R queryMy(Integer uid) {
        LambdaQueryWrapper<Order> wrapper=new LambdaQueryWrapper<>();
        wrapper.orderByDesc(Order::getCreateTime);
        wrapper.eq(Order::getUid,uid);
        return R.ok(dao.selectList(wrapper));
    }
}